home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso / 1138 / source.zip / THREAD.C < prev    next >
C/C++ Source or Header  |  1995-02-06  |  5KB  |  233 lines

  1. /*      thread.c -- Threads messages for easier perusal
  2.     This file is part of Paperboy, an offline mail/newsreader for Windows
  3.     Copyright (C) 1995  Michael H. Vartanian
  4.         vart@clark.net
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include "error.h"
  24. #include "soup.h"
  25. #include "structs.h"
  26. #include "msgs.h"
  27. #include "areas.h"
  28. #include "thread.h"
  29.  
  30. struct llmsg ** hold;
  31.  
  32. char * stripsubject (char * subject)
  33. {
  34.     /* Remove leading RE: to get down to a basic subject */
  35.     char * stripped;
  36.     int replen;    /* Cache length for performance (loop invariant)*/
  37.  
  38.     assert(subject!=NULL);
  39.     stripped=subject;
  40.  
  41.     replen=strlen(REPLYSTR);
  42.  
  43.     while (_fstrnicmp(stripped,REPLYSTR,replen)==0)
  44.     {
  45.         stripped+=replen;
  46.     }
  47.  
  48.     return stripped;
  49. }
  50.  
  51.  
  52.  
  53. static int comparemsg (const void * m1, const void * m2)
  54. {
  55.     struct llmsg * msg1, * msg2;
  56.     struct llmsg ** p;
  57.     time_t comp;
  58.  
  59.     p=NULL;
  60.     msg1=NULL;
  61.     msg2=NULL;
  62.     
  63.     assert(m1!=NULL);
  64.     assert(m2!=NULL);
  65.     if (m1==m2) return 0;
  66.     p=(struct llmsg **)m1;
  67.     msg1=(struct llmsg *)*p;
  68.     p=(struct llmsg **)m2;
  69.     msg2=(struct llmsg *)*p;
  70.     
  71.     /* I've had loads of trouble debugging this routine, can't you tell ? */
  72.     assert(msg1!=NULL);
  73.     assert(msg2!=NULL);
  74.     if (msg1==msg2) return 0;
  75.     assert(msg1->magic==MSGMAGIC);    
  76.     assert(msg2->magic==MSGMAGIC);
  77.  
  78.     comp=msg1->thread_idate - msg2->thread_idate;
  79.  
  80.     if (comp==0)    /* Same thread, sort by date */
  81.     {
  82.         /* Always put base of thread first, regardless of date
  83.            (our date routine farkles timezones) */
  84.         assert(msg1->subject!=NULL);
  85.         assert(msg2->subject!=NULL);
  86.         if (stripsubject(msg1->subject)==msg1->subject) return -1;
  87.         if (stripsubject(msg2->subject)==msg2->subject) return 1;   
  88.         comp=msg1->idate - msg2->idate;
  89.     }
  90.  
  91.     if (comp>0) return 1;
  92.     if (comp<0) return -1;
  93.     return 0;
  94. }
  95.  
  96. void ComputeBaseThreadDate(struct llareas * area)
  97. {
  98. /* For every message in this group, find the date of it's earliest
  99.    thread.  
  100.    We're not terribly efficient in this routine O(n^2), but it works.
  101.  */
  102.     struct llmsg * cur, * inner;
  103.     char * subj1, * subj2;
  104.  
  105.     assert(area!=NULL);
  106.  
  107.     cur=area->head;
  108.  
  109.     while (cur)
  110.     {
  111.         subj1=stripsubject(cur->subject);
  112.         inner=area->head;
  113.         while (inner)
  114.         {
  115.             subj2=stripsubject(inner->subject);
  116.             if (!strnicmp(subj1,subj2,SIGTHREAD)) /* Base subjects are the same */
  117.             {
  118.                 if (inner->idate < cur->thread_idate)
  119.                     cur->thread_idate=inner->idate;
  120.             }
  121.             inner=inner->next;
  122.         }
  123.         cur=cur->next;
  124.     }
  125. }
  126.  
  127.  
  128.  
  129. int DLLFUNC ThreadMsgs (int index)
  130. {
  131.     struct llareas * area;
  132.     struct llmsg * msghead;
  133.     int nummsg;
  134.     int pt;
  135.  
  136.     assert(index>0);
  137.     assert(index<=GetNumAreas());
  138.     area=findarea(index);
  139.     
  140.     assert(area!=NULL);
  141.  
  142.     ComputeBaseThreadDate(area); 
  143.  
  144.     nummsg=GetNumMsgs(index);
  145.     
  146.     assert(nummsg!=0);
  147.  
  148.     /* We create an array large enough to hold pointers to all messages */
  149.     hold=(struct llmsg **)malloc(sizeof(struct llmsg *) * nummsg);
  150.     if (hold==NULL) { errortext="ThreadMsgs: pointer array"; return ERRMEM; }
  151.     memset(hold, 0, sizeof(struct llmsg *) * nummsg );
  152.  
  153.     /* Now stuff pointers to each element into the array */
  154.     msghead=area->head;
  155.     assert(msghead!=NULL);
  156.     
  157.     for (pt=0; pt<nummsg; pt++)
  158.     {   
  159.         assert(msghead!=NULL);                     
  160.         assert(msghead->magic==MSGMAGIC);
  161.         hold[pt]=msghead;
  162.         msghead=msghead->next;
  163.     }
  164.     
  165.     assert(pt==nummsg);
  166.  
  167.     /* Sort the array */
  168.     qsort(hold, nummsg, sizeof(struct llmsg *), comparemsg);
  169.  
  170.     /* Reassemble the linked list */
  171.     area->head=hold[0];
  172.  
  173.     for (pt=0; pt<nummsg-1; pt++)
  174.         hold[pt]->next=hold[pt+1];
  175.  
  176.     hold[pt]->next=NULL;    /* End of list */
  177.  
  178.     free(hold);
  179.     return 0;
  180. }
  181.  
  182. void reverseorder (struct llareas * area)
  183. {
  184.     struct llmsg * msghead;
  185.     struct llmsg * cur;
  186.     
  187.     int nummsg;
  188.     int pt;
  189.  
  190.     assert (area!=NULL);
  191.     
  192.     cur=area->head;
  193.     
  194.     nummsg=0;
  195.     while (cur!=NULL)
  196.     {
  197.         cur=cur->next;
  198.         nummsg++;
  199.     }
  200.  
  201.     if (nummsg==0) return;
  202.     assert(nummsg!=0);
  203.  
  204.     /* We create an array large enough to hold pointers to all messages */
  205.     hold=(struct llmsg **)malloc(sizeof(struct llmsg *) * nummsg);
  206.     if (hold==NULL) { errortext="ThreadMsgs: pointer array"; return; }
  207.     memset(hold, 0, sizeof(struct llmsg *) * nummsg );
  208.  
  209.     /* Now stuff pointers to each element into the array */
  210.     msghead=area->head;
  211.     assert(msghead!=NULL);
  212.     
  213.     /* for (pt=0; pt<nummsg; pt++) */
  214.     for (pt=nummsg-1; pt>=0; pt--)
  215.     {   
  216.         assert(msghead!=NULL);                     
  217.         assert(msghead->magic==MSGMAGIC);
  218.         hold[pt]=msghead;
  219.         msghead=msghead->next;
  220.     }
  221.     
  222.     /* Reassemble the linked list */
  223.     area->head=hold[0];
  224.  
  225.     for (pt=0; pt<nummsg-1; pt++)
  226.         hold[pt]->next=hold[pt+1];
  227.  
  228.     hold[pt]->next=NULL;    /* End of list */
  229.  
  230.     free(hold);
  231.  
  232. }
  233.